<template>
  <div class="attraction-detail">
    <div class="page-header" v-if="attraction">
      <el-page-header @back="goBack">
        <template #content>
          <h1 class="page-title">
            <el-icon><MapLocation /></el-icon>
            {{ attraction.name }}
          </h1>
        </template>
      </el-page-header>
    </div>

    <div v-loading="loading" class="detail-content">
      <el-row :gutter="20" v-if="attraction">
        <!-- 左侧：图片和基本信息 -->
        <el-col :xs="24" :sm="24" :md="14" :lg="14">
          <!-- 图片轮播 -->
          <el-card class="image-card" shadow="hover">
            <el-carousel
              v-if="images.length > 0"
              :interval="4000"
              :type="images.length >= 3 ? 'card' : ''"
              :height="carouselHeight"
              indicator-position="outside"
            >
              <el-carousel-item v-for="(img, index) in images" :key="img.id || `img_${index}`">
                <!-- 第一张图片立即加载，其他图片懒加载 -->
                <LazyImage
                  v-if="img.url"
                  :src="img.url"
                  :preview-src-list="previewImageList.length > 0 ? previewImageList : undefined"
                  :initial-index="Math.min(index, previewImageList.length - 1)"
                  fit="cover"
                  :height="carouselHeight"
                  width="100%"
                  :root-margin="index === 0 ? '0px' : '100px'"
                  image-class="carousel-image"
                  :image-style="{ width: '100%', height: '100%' }"
                />
                <div v-else class="image-error-slot">
                  <el-icon><PictureRounded /></el-icon>
                  <span>图片URL无效</span>
                </div>
              </el-carousel-item>
            </el-carousel>
            <div v-else class="no-image">
              <el-empty description="暂无图片" :image-size="150" />
            </div>
          </el-card>

          <!-- 基本信息 -->
          <el-card class="info-card" shadow="hover">
            <template #header>
              <div class="card-header">
                <span>基本信息</span>
              </div>
            </template>
            <el-descriptions :column="descriptionsColumn" border>
              <el-descriptions-item label="景点名称">
                {{ attraction.name }}
              </el-descriptions-item>
              <el-descriptions-item label="景点分类">
                <el-tag :type="getCategoryType(attraction.category)">
                  {{ attraction.category_display || '文化古迹' }}
                </el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="门票价格" :span="2">
                <span class="price-text">¥{{ attraction.ticket_price }}</span>
                <span v-if="attraction.ticket_price == 0" class="free-tag">免费</span>
              </el-descriptions-item>
              <el-descriptions-item label="建议游览时间" :span="2">
                {{ attraction.visit_time ? attraction.visit_time + '分钟' : '暂无' }}
              </el-descriptions-item>
              <el-descriptions-item label="开放时间" :span="2">
                <div v-if="attraction.open_time && attraction.close_time" class="opening-hours">
                  <el-tag type="success" size="small" style="margin-right: 8px;">
                    <el-icon><Clock /></el-icon>
                  </el-tag>
                  <span class="hours-text">
                    {{ formatTime(attraction.open_time) }} - {{ formatTime(attraction.close_time) }}
                  </span>
                  <el-tag 
                    v-if="isCurrentlyOpen === true" 
                    type="success" 
                    size="small" 
                    effect="dark"
                    style="margin-left: 8px;"
                  >
                    营业中
                  </el-tag>
                  <el-tag 
                    v-else-if="isCurrentlyOpen === false" 
                    type="info" 
                    size="small" 
                    effect="plain"
                    style="margin-left: 8px;"
                  >
                    已关闭
                  </el-tag>
                </div>
                <span v-else class="text-muted">
                  <el-icon><Clock /></el-icon>
                  全天开放
                </span>
              </el-descriptions-item>
              <el-descriptions-item label="地址" :span="2">
                <el-icon><Location /></el-icon>
                {{ attraction.address || '暂无地址' }}
              </el-descriptions-item>
              <el-descriptions-item label="坐标" :span="2" v-if="attraction.longitude && attraction.latitude">
                经度: {{ attraction.longitude }}, 纬度: {{ attraction.latitude }}
              </el-descriptions-item>
              <el-descriptions-item label="坐标" :span="2" v-else>
                <span class="text-muted">暂无坐标信息</span>
              </el-descriptions-item>
            </el-descriptions>
          </el-card>

          <!-- 景点描述 -->
          <el-card class="description-card" shadow="hover" v-if="attraction.description">
            <template #header>
              <div class="card-header">
                <span>景点介绍</span>
              </div>
            </template>
            <div class="description-content">
              {{ attraction.description }}
            </div>
          </el-card>
        </el-col>

        <!-- 右侧：评分、评价、操作 -->
        <el-col :xs="24" :sm="24" :md="10" :lg="10">
          <!-- 评分和热度 -->
          <el-card class="rating-card" shadow="hover">
            <div class="rating-section">
              <div class="rating-score">
                <span class="score">{{ attraction.rating || 4.5 }}</span>
                <el-rate
                  :model-value="(attraction.rating || 4.5) / 1"
                  disabled
                  show-score
                  text-color="#ff9900"
                  score-template="{value}"
                />
              </div>
              <div class="popularity-section">
                <el-progress
                  :percentage="(attraction.popularity / 100) * 100"
                  :color="getPopularityColor(attraction.popularity)"
                  :show-text="false"
                />
                <div class="popularity-text">
                  热度: {{ attraction.popularity }}
                </div>
              </div>
            </div>
          </el-card>

          <!-- 快捷操作 -->
          <el-card class="action-card" shadow="hover">
            <template #header>
              <div class="card-header">
                <span>快捷操作</span>
              </div>
            </template>
            <div class="action-buttons">
              <el-button
                type="primary"
                size="large"
                :icon="MapLocation"
                @click="planRoute"
                style="width: 100%; margin-bottom: 10px;"
              >
                规划路线
              </el-button>
              <el-button
                type="success"
                size="large"
                :icon="Location"
                @click="viewOnMap"
                style="width: 100%; margin-bottom: 10px;"
              >
                查看地图
              </el-button>
              <el-button
                v-if="isAuthenticated"
                type="warning"
                size="large"
                :icon="Upload"
                @click="showUploadDialog = true"
                style="width: 100%; margin-bottom: 10px;"
              >
                上传图片
              </el-button>
              <el-button
                type="info"
                size="large"
                :icon="Share"
                @click="shareAttraction"
                style="width: 100%; margin-bottom: 10px;"
              >
                分享景点
              </el-button>
              <el-button
                v-if="isAuthenticated"
                :type="attraction && attraction.is_favorited ? 'warning' : 'default'"
                size="large"
                :icon="attraction && attraction.is_favorited ? StarFilled : Star"
                @click="toggleFavorite"
                :loading="favoriting"
                :disabled="!attraction || !attraction.id"
                style="width: 100%;"
              >
                {{ attraction && attraction.is_favorited ? '已收藏' : '收藏景点' }}
              </el-button>
            </div>
          </el-card>

          <!-- 评价列表 -->
          <el-card class="reviews-card" shadow="hover">
            <template #header>
              <div class="card-header">
                <span>用户评价 ({{ reviews.length }})</span>
              </div>
            </template>
            <div v-if="reviews.length > 0" class="reviews-list">
              <div
                v-for="(review, index) in reviews.slice(0, 5)"
                :key="review.id || `review_${index}`"
                class="review-item"
              >
                <div class="review-header">
                  <span class="review-user">{{ review.user_username || review.username || '匿名用户' }}</span>
                  <el-rate
                    :model-value="review.rating || 0"
                    disabled
                    size="small"
                    :max="5"
                  />
                  <span class="review-date">{{ review.created_at ? formatDate(review.created_at) : '' }}</span>
                </div>
                <div class="review-content" v-if="review.content">
                  {{ review.content }}
                </div>
              </div>
            </div>
            <el-empty v-else description="暂无评价" :image-size="100" />
          </el-card>
        </el-col>
      </el-row>
    </div>

    <!-- 地图对话框 -->
    <el-dialog
      v-model="mapDialogVisible"
      :title="attraction?.name + ' - 位置地图'"
      width="900px"
    >
      <div id="attraction-detail-map" :style="{ width: '100%', height: mapHeight }"></div>
    </el-dialog>

    <!-- 上传图片对话框 -->
    <el-dialog
      v-model="showUploadDialog"
      title="上传景点图片"
      width="500px"
      @close="resetUploadForm"
    >
      <el-form :model="uploadForm" label-width="100px">
        <el-form-item label="选择图片">
          <el-upload
            ref="uploadRef"
            :action="uploadAction"
            :headers="uploadHeaders"
            :data="uploadData"
            :name="'image'"
            :file-list="uploadFileList"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :on-remove="handleUploadRemove"
            :before-upload="beforeUpload"
            :limit="5"
            :multiple="true"
            list-type="picture-card"
            :class="{ 'hide-upload': uploadFileList.length >= 5 }"
            :disabled="uploading"
          >
            <el-icon><Plus /></el-icon>
            <template #tip>
              <div class="el-upload__tip">
                支持 JPG、PNG、GIF 格式，单张图片不超过5MB，最多5张
              </div>
            </template>
          </el-upload>
        </el-form-item>
        <el-form-item label="设为封面">
          <el-switch v-model="uploadForm.is_primary" />
          <span style="margin-left: 10px; color: #909399; font-size: 12px;">
            设置为景点封面图片
          </span>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="showUploadDialog = false">取消</el-button>
        <el-button type="primary" @click="submitUpload" :loading="uploading">
          上传
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useStore } from 'vuex'
import { ElMessage } from 'element-plus'
import { 
  Location, 
  MapLocation, 
  Share, 
  Star, 
  StarFilled, 
  PictureRounded, 
  Upload, 
  Plus, 
  Clock 
} from '@element-plus/icons-vue'
import TravelAPI from '../api/travel'
import { AMapUtil } from '../utils/amap'
import { getApiBaseUrl, getImageUrl as getImageUrlUtil } from '../utils/apiConfig'
import { handleApiError } from '../utils/errorHandler'
import logger from '../utils/logger'
import LazyImage from '../components/LazyImage.vue'

export default {
  name: 'AttractionDetail',
  components: {
    LazyImage
  },
  setup() {
    const route = useRoute()
    const router = useRouter()
    const store = useStore()
    const loading = ref(false)
    const attraction = ref(null)
    const images = ref([])
    const reviews = ref([])
    const mapDialogVisible = ref(false)
    const amapUtil = ref(null)
    const favoriting = ref(false)
    const showUploadDialog = ref(false)
    const uploading = ref(false)
    const uploadRef = ref(null)
    const uploadFileList = ref([])
    const uploadForm = ref({
      is_primary: false
    })
    
    const isAuthenticated = computed(() => store.getters.isAuthenticated)

    const isMobile = ref(typeof window !== 'undefined' ? window.innerWidth < 768 : false)

    /**
     * 处理窗口大小变化，更新移动端断点状态
     */
    const handleResize = () => {
      if (typeof window === 'undefined') return
      isMobile.value = window.innerWidth < 768
    }

    /**
     * 根据屏幕宽度返回描述列表列数
     */
    const descriptionsColumn = computed(() => (isMobile.value ? 1 : 2))

    /**
     * 根据屏幕宽度返回轮播高度
     */
    const carouselHeight = computed(() => (isMobile.value ? '240px' : '400px'))

    /**
     * 根据屏幕宽度返回地图高度
     */
    const mapHeight = computed(() => (isMobile.value ? '360px' : '500px'))
    
    // 上传配置
    const uploadAction = computed(() => {
      if (!attraction.value?.id) return ''
      try {
        const baseUrl = getApiBaseUrl()
        return `${baseUrl}/api/attractions/${attraction.value.id}/upload_image/`
      } catch (error) {
        console.error('获取API基础URL失败:', error)
        return ''
      }
    })
    
    const uploadHeaders = computed(() => {
      try {
        const token = store.state.token || (typeof window !== 'undefined' && window.localStorage ? window.localStorage.getItem('token') : null)
        return {
          'Authorization': token ? `Token ${token}` : ''
        }
      } catch (error) {
        console.error('获取上传headers失败:', error)
        return {}
      }
    })
    
    const uploadData = computed(() => {
      return {
        is_primary: uploadForm.value.is_primary || false
      }
    })

    // 工具函数：获取图片URL
    const getImageUrl = (url) => {
      if (!url) return ''
      try {
        // 确保 getImageUrlUtil 已正确导入
        if (typeof getImageUrlUtil !== 'function') {
          console.error('getImageUrlUtil 未正确导入')
          return url || ''
        }
        return getImageUrlUtil(url)
      } catch (error) {
        console.error('获取图片URL失败:', error)
        return url || ''
      }
    }

    // 预览图片列表
    const previewImageList = computed(() => {
      if (!images.value || images.value.length === 0) return []
      // 直接使用img.url，因为已经在fetchAttractionImages中处理过了
      return images.value
        .map(img => img.url)
        .filter(url => url && url.trim() !== '') // 过滤掉空URL和空白字符串
    })

    // 获取分类类型
    const getCategoryType = (category) => {
      if (!category) return 'info'
      const types = {
        'cultural': 'warning',
        'natural': 'success',
        'modern': 'info',
        'food': 'danger'
      }
      return types[category] || 'info'
    }

    // 获取热度颜色
    const getPopularityColor = (popularity) => {
      if (popularity === null || popularity === undefined) return '#909399'
      const num = Number(popularity)
      if (isNaN(num)) return '#909399'
      if (num >= 80) return '#67c23a'
      if (num >= 60) return '#e6a23c'
      if (num >= 40) return '#f56c6c'
      return '#909399'
    }

    // 格式化时间
    const formatTime = (time) => {
      if (!time) return ''
      try {
        if (typeof time === 'string') {
          // 如果是时间字符串，提取HH:MM部分
          if (time.includes(':')) {
            return time.substring(0, 5) // HH:MM
          }
          return time
        }
        // 如果是Date对象或其他类型
        if (time instanceof Date) {
          return `${String(time.getHours()).padStart(2, '0')}:${String(time.getMinutes()).padStart(2, '0')}`
        }
        return String(time)
      } catch (error) {
        console.error('格式化时间失败:', error)
        return String(time)
      }
    }

    // 检查景点当前是否开放
    const isCurrentlyOpen = computed(() => {
      if (!attraction.value?.open_time || !attraction.value?.close_time) {
        return null // 无开放时间信息
      }
      
      const now = new Date()
      const currentTime = now.getHours() * 60 + now.getMinutes() // 当前时间（分钟）
      
      const openTimeStr = formatTime(attraction.value.open_time)
      const closeTimeStr = formatTime(attraction.value.close_time)
      
      const [openHour, openMin] = openTimeStr.split(':').map(Number)
      const [closeHour, closeMin] = closeTimeStr.split(':').map(Number)
      
      const openMinutes = openHour * 60 + openMin
      const closeMinutes = closeHour * 60 + closeMin
      
      // 如果关闭时间小于开放时间，说明跨天（如 22:00 - 02:00）
      if (closeMinutes < openMinutes) {
        return currentTime >= openMinutes || currentTime <= closeMinutes
      } else {
        return currentTime >= openMinutes && currentTime <= closeMinutes
      }
    })

    const handleImageError = (event) => {
      // 图片加载失败时的处理
      try {
        if (event && event.target && event.target.tagName === 'IMG') {
          // el-image组件会自动显示错误插槽，这里可以添加额外的错误处理逻辑
          logger.warn('图片加载失败:', event.target.src)
        }
      } catch (error) {
        logger.error('处理图片错误时发生异常:', error)
      }
    }

    const formatDate = (date) => {
      if (!date) return ''
      try {
        const d = new Date(date)
        // 检查日期是否有效
        if (isNaN(d.getTime())) {
          return ''
        }
        return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
      } catch (error) {
        console.error('日期格式化失败:', error)
        return ''
      }
    }

    const fetchAttractionDetail = async () => {
      const attractionId = route.params.id || route.query.id
      if (!attractionId) {
        ElMessage.error('景点ID不存在')
        router.push('/attractions')
        return
      }

      loading.value = true
      try {
        // 获取景点详情
        const attractionData = await TravelAPI.getAttractionDetail(attractionId)
        
        // 确保数据格式正确
        if (!attractionData) {
          throw new Error('获取景点详情失败：返回数据为空')
        }
        
        // 设置景点数据
        attraction.value = attractionData

        // 并行获取图片和评价，避免其中一个失败影响另一个
        const promises = []
        
        // 获取图片（需要等待attraction.value设置完成）
        if (attractionId && attraction.value) {
          promises.push(
            fetchAttractionImages(attractionId).catch(error => {
              logger.error('获取景点图片失败:', error)
              // 图片获取失败不影响页面显示，只记录错误
            })
          )
        }

        // 获取评价
        if (attractionId) {
          promises.push(
            fetchAttractionReviews(attractionId).catch(error => {
              logger.error('获取景点评价失败:', error)
              // 评价获取失败不影响页面显示，只记录错误
            })
          )
        }
        
        // 等待所有请求完成（即使有失败也不抛出错误）
        await Promise.allSettled(promises)
      } catch (error) {
        handleApiError(error, { defaultMessage: '获取景点详情失败' })
        let errorMessage = '获取景点详情失败'
        if (error.response) {
          const status = error.response.status
          if (status === 404) {
            errorMessage = '景点不存在或已被删除'
          } else if (status === 500) {
            errorMessage = '服务器错误，请稍后重试'
          } else if (error.response.data?.error) {
            errorMessage = error.response.data.error
          } else if (error.response.data?.detail) {
            errorMessage = error.response.data.detail
          }
        } else if (error.message) {
          if (error.message.includes('timeout')) {
            errorMessage = '请求超时，请检查网络连接'
          } else if (error.message.includes('Network Error')) {
            errorMessage = '网络错误，请检查网络连接'
          }
        }
        ElMessage.error(errorMessage)
        setTimeout(() => {
          router.push('/attractions')
        }, 2000)
      } finally {
        loading.value = false
      }
    }

    const fetchAttractionImages = async (attractionId) => {
      try {
        // 确保attraction.value已经设置
        if (!attraction.value) {
          console.warn('景点数据未加载，无法获取图片')
          return
        }
        
        // 优先使用景点详情中的高德地图图片
        if (attraction.value?.amap_images && Array.isArray(attraction.value.amap_images) && attraction.value.amap_images.length > 0) {
          const processedImages = attraction.value.amap_images
            .map((url, index) => {
              if (!url) return null
              const processedUrl = getImageUrl(url)
              return processedUrl ? {
                id: `amap_${index}`,
                url: processedUrl,
                name: `amap_image_${index}.jpg`
              } : null
            })
            .filter(img => img !== null && img.url) // 过滤掉空URL和null值
          
          if (processedImages.length > 0) {
            images.value = processedImages
            return
          }
        }
        
        // 如果没有amap_images，尝试amap_image_urls
        if (attraction.value?.amap_image_urls && Array.isArray(attraction.value.amap_image_urls) && attraction.value.amap_image_urls.length > 0) {
          const processedImages = attraction.value.amap_image_urls
            .map((url, index) => {
              if (!url) return null
              const processedUrl = getImageUrl(url)
              return processedUrl ? {
                id: `amap_${index}`,
                url: processedUrl,
                name: `amap_image_${index}.jpg`
              } : null
            })
            .filter(img => img !== null && img.url) // 过滤掉空URL和null值
          
          if (processedImages.length > 0) {
            images.value = processedImages
            return
          }
        }
        
        // 调用API获取图片
        const response = await TravelAPI.getAttractionImages(attractionId)
        
        if (!response || response.length === 0) {
          // 如果没有图片，尝试使用主图
          if (attraction.value?.primary_image) {
            const primaryUrl = getImageUrl(attraction.value.primary_image)
            images.value = primaryUrl ? [{
              id: 'primary',
              url: primaryUrl,
              name: 'primary_image.jpg'
            }] : []
          } else {
            images.value = []
          }
          return
        }
        
        images.value = (response || [])
          .map(img => {
            try {
              // 图片URL可能在image字段中
              let imageUrl = img.image || img.url || img.image_url
              
              // 如果URL为空，尝试其他字段
              if (!imageUrl && img.image_file) {
                imageUrl = img.image_file
              }
              
              // 如果仍然没有URL，跳过这个图片
              if (!imageUrl) {
                return null
              }
              
              // 确保 getImageUrl 函数可用
              if (typeof getImageUrl !== 'function') {
                console.error('getImageUrl 函数未定义')
                return null
              }
              
              const processedUrl = getImageUrl(imageUrl)
              
              // 如果处理后的URL为空，跳过这个图片
              if (!processedUrl || processedUrl.trim() === '') {
                return null
              }
              
              return {
                id: img.id || `img_${Math.random()}`,
                url: processedUrl,
                name: `image_${img.id || 'unknown'}.jpg`
              }
            } catch (error) {
              console.error('处理图片数据时出错:', error)
              return null
            }
          })
          .filter(img => img !== null && img.url && img.url.trim() !== '') // 过滤掉null和空URL
        
        // 如果API返回为空，尝试使用主图
        if (images.value.length === 0 && attraction.value?.primary_image) {
          const primaryUrl = getImageUrl(attraction.value.primary_image)
          if (primaryUrl) {
            images.value = [{
              id: 'primary',
              url: primaryUrl,
              name: 'primary_image.jpg'
            }]
          }
        }
      } catch (error) {
        logger.error('获取景点图片失败:', error)
        images.value = []
        
        // 如果API失败，尝试使用主图
        if (attraction.value?.primary_image) {
          const primaryUrl = getImageUrl(attraction.value.primary_image)
          if (primaryUrl) {
            images.value = [{
              id: 'primary',
              url: primaryUrl,
              name: 'primary_image.jpg'
            }]
          }
        }
      }
    }

    const fetchAttractionReviews = async (attractionId) => {
      try {
        const response = await TravelAPI.getAttractionReviews(attractionId)
        reviews.value = response || []
      } catch (error) {
        logger.error('获取景点评价失败:', error)
        reviews.value = []
      }
    }

    const goBack = () => {
      router.back()
    }

    const planRoute = () => {
      if (attraction.value) {
        router.push({
          path: '/route-plan',
          query: {
            start_attraction_id: attraction.value.id,
            must_visit: attraction.value.id
          }
        })
      }
    }

    const viewOnMap = async () => {
      if (!attraction.value) return
      
      mapDialogVisible.value = true
      await new Promise(resolve => setTimeout(resolve, 300))

      try {
        const apiKey = process.env.VUE_APP_AMAP_KEY || ''
        if (!apiKey || apiKey === 'your_amap_api_key') {
          ElMessage.error('高德地图API Key未配置')
          return
        }

        if (!amapUtil.value) {
          amapUtil.value = new AMapUtil(apiKey)
        }

        if (amapUtil.value.map) {
          amapUtil.value.map.destroy()
          amapUtil.value.map = null
        }

        await new Promise(resolve => setTimeout(resolve, 100))
        
        await amapUtil.value.initMap('attraction-detail-map', {
          center: [parseFloat(attraction.value.longitude), parseFloat(attraction.value.latitude)],
          zoom: 15
        })

        const infoContent = `
          <div style="padding: 10px;">
            <h3 style="margin: 0 0 10px 0;">${attraction.value.name}</h3>
            <p style="margin: 5px 0;"><strong>地址:</strong> ${attraction.value.address || '暂无'}</p>
            <p style="margin: 5px 0;"><strong>门票:</strong> ¥${attraction.value.ticket_price}</p>
          </div>
        `

        amapUtil.value.addMarkers([{
          lng: parseFloat(attraction.value.longitude),
          lat: parseFloat(attraction.value.latitude),
          title: attraction.value.name,
          info: infoContent
        }])
      } catch (error) {
        handleApiError(error, { defaultMessage: '地图初始化失败' })
      }
    }

    const shareAttraction = () => {
      // 确保attraction.value存在
      if (!attraction.value) {
        ElMessage.warning('景点信息未加载，无法分享')
        return
      }

      if (navigator.share && typeof navigator.share === 'function') {
        navigator.share({
          title: attraction.value.name || '南昌景点',
          text: attraction.value.description || `欢迎参观${attraction.value.name || '这个景点'}`,
          url: window.location.href
        }).catch(err => {
          logger.error('分享失败:', err)
          ElMessage.error('分享失败，请稍后重试')
        })
      } else {
        // 复制链接到剪贴板
        const url = window.location.href
        if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
          navigator.clipboard.writeText(url).then(() => {
            ElMessage.success('链接已复制到剪贴板')
          }).catch(() => {
            ElMessage.info('请手动复制链接: ' + url)
          })
        } else {
          // 降级方案：使用传统方法
          const textArea = document.createElement('textarea')
          textArea.value = url
          textArea.style.position = 'fixed'
          textArea.style.opacity = '0'
          document.body.appendChild(textArea)
          textArea.select()
          try {
            document.execCommand('copy')
            ElMessage.success('链接已复制到剪贴板')
          } catch (err) {
            logger.error('复制失败:', err)
            ElMessage.info('请手动复制链接: ' + url)
          }
          document.body.removeChild(textArea)
        }
      }
    }

    const toggleFavorite = async () => {
      if (!isAuthenticated.value) {
        ElMessage.warning('请先登录')
        router.push('/login')
        return
      }

      if (!attraction.value?.id) return

      favoriting.value = true
      try {
        const isFavorited = attraction.value.is_favorited
        await TravelAPI.toggleFavorite(attraction.value.id, !isFavorited)
        attraction.value.is_favorited = !isFavorited
        attraction.value.favorites_count = isFavorited 
          ? (attraction.value.favorites_count || 1) - 1 
          : (attraction.value.favorites_count || 0) + 1
        ElMessage.success(isFavorited ? '已取消收藏' : '收藏成功')
      } catch (error) {
        handleApiError(error, { defaultMessage: '收藏操作失败' })
      } finally {
        favoriting.value = false
      }
    }

    onMounted(() => {
      fetchAttractionDetail()
      handleResize()
      if (typeof window !== 'undefined') {
        window.addEventListener('resize', handleResize)
      }
    })

    onUnmounted(() => {
      if (typeof window !== 'undefined') {
        window.removeEventListener('resize', handleResize)
      }
    })

    // 上传前验证
    const beforeUpload = (file) => {
      const isImage = file.type.startsWith('image/')
      const isLt5M = file.size / 1024 / 1024 < 5

      if (!isImage) {
        ElMessage.error('只能上传图片文件！')
        return false
      }
      if (!isLt5M) {
        ElMessage.error('图片大小不能超过5MB！')
        return false
      }
      return true
    }

    // 上传成功
    const handleUploadSuccess = () => {
      ElMessage.success('图片上传成功！')
      // 重新加载图片列表
      if (attraction.value?.id) {
        fetchAttractionImages(attraction.value.id)
      }
    }

    // 上传失败
    const handleUploadError = (error) => {
      ElMessage.error('图片上传失败，请重试')
      logger.error('图片上传失败:', error)
    }

    // 移除文件
    const handleUploadRemove = (file) => {
      const index = uploadFileList.value.findIndex(item => item.uid === file.uid)
      if (index > -1) {
        uploadFileList.value.splice(index, 1)
      }
    }

    // 提交上传
    const submitUpload = () => {
      if (uploadFileList.value.length === 0) {
        ElMessage.warning('请至少选择一张图片')
        return
      }
      
      // el-upload会自动上传，这里只需要关闭对话框
      // 实际上传由el-upload组件处理
      ElMessage.info('图片正在上传中...')
    }

    // 重置上传表单
    const resetUploadForm = () => {
      uploadFileList.value = []
      uploadForm.value.is_primary = false
      if (uploadRef.value) {
        uploadRef.value.clearFiles()
      }
    }

    return {
      loading,
      attraction,
      images,
      reviews,
      mapDialogVisible,
      isMobile,
      descriptionsColumn,
      carouselHeight,
      mapHeight,
      previewImageList,
      getImageUrl,
      getCategoryType,
      getPopularityColor,
      formatTime,
      formatDate,
      isCurrentlyOpen,
      goBack,
      planRoute,
      viewOnMap,
      shareAttraction,
      toggleFavorite,
      isAuthenticated,
      favoriting,
      handleImageError,
      showUploadDialog,
      uploading,
      uploadRef,
      uploadFileList,
      uploadForm,
      uploadAction,
      uploadHeaders,
      uploadData,
      beforeUpload,
      handleUploadSuccess,
      handleUploadError,
      handleUploadRemove,
      submitUpload,
      resetUploadForm,
      fetchAttractionDetail,
      fetchAttractionImages,
      fetchAttractionReviews,
      // 图标组件
      Star,
      StarFilled,
      Location,
      MapLocation,
      Share,
      PictureRounded,
      Upload,
      Plus,
      Clock
    }
  }
}
</script>

<style scoped>
.attraction-detail {
  padding: clamp(10px, 2vw, 20px);
  max-width: 1400px;
  margin: 0 auto;
  /* 南昌旅游特色：天空蓝渐变背景 */
  background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 50%, #90CAF9 100%);
  min-height: 100vh;
  animation: fadeIn 0.5s ease-in;
}

/* 响应式设计：移动端优化 */
@media (max-width: 768px) {
  .no-image {
    height: 260px;
  }

  /* 对话框宽度适配移动端 */
  :deep(.el-dialog) {
    width: 95% !important;
    margin: 5vh auto !important;
  }
}

.page-header {
  margin-bottom: 30px;
  padding: 20px;
  background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(227,242,253,0.7) 100%);
  border-radius: 16px;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 4px 20px rgba(200, 16, 46, 0.1);
  position: relative;
}

.page-header::before {
  content: '';
  position: absolute;
  top: -2px;
  left: -2px;
  right: -2px;
  bottom: -2px;
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 50%, #1E88E5 100%);
  border-radius: 16px;
  z-index: -1;
  opacity: 0.3;
  filter: blur(8px);
}

.page-title {
  font-size: clamp(24px, 4vw, 32px);
  font-weight: 700;
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
}

.page-title .el-icon {
  font-size: 1.2em;
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.detail-content {
  margin-top: 20px;
}

.image-card {
  margin-bottom: 20px;
}

.no-image {
  height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.info-card,
.description-card,
.rating-card,
.action-card,
.reviews-card {
  margin-bottom: 20px;
  border-radius: 16px;
  border: 1px solid rgba(200, 16, 46, 0.12);
  background: linear-gradient(135deg, rgba(255,255,255,0.98) 0%, rgba(227,242,253,0.85) 100%);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 4px 20px rgba(200, 16, 46, 0.08), 0 1px 3px rgba(0, 0, 0, 0.05);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
}

.info-card::before,
.description-card::before,
.rating-card::before,
.action-card::before,
.reviews-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, #C8102E 0%, #D4AF37 50%, #1E88E5 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.info-card:hover::before,
.description-card:hover::before,
.rating-card:hover::before,
.action-card:hover::before,
.reviews-card:hover::before {
  opacity: 1;
}

.info-card:hover,
.description-card:hover,
.rating-card:hover,
.action-card:hover,
.reviews-card:hover {
  box-shadow: 0 12px 32px rgba(200, 16, 46, 0.15), 0 4px 8px rgba(0, 0, 0, 0.1);
  transform: translateY(-4px);
  border-color: rgba(212, 175, 55, 0.4);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  font-size: 16px;
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.opening-hours {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.hours-text {
  font-weight: 500;
  color: #303133;
  font-size: 15px;
}

.text-muted {
  color: #909399;
  display: flex;
  align-items: center;
  gap: 5px;
}

.price-text {
  font-size: 28px;
  font-weight: 700;
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-right: 10px;
}

.free-tag {
  background: #67c23a;
  color: white;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
}

.description-content {
  line-height: 1.8;
  color: #606266;
  white-space: pre-wrap;
}

.rating-section {
  text-align: center;
}

.rating-score {
  margin-bottom: 20px;
}

.score {
  font-size: 48px;
  font-weight: bold;
  /* 南昌红主题色 */
  color: #C8102E;
  display: block;
  margin-bottom: 10px;
  text-shadow: 0 2px 8px rgba(200, 16, 46, 0.2);
}

.popularity-section {
  margin-top: 20px;
}

.popularity-text {
  margin-top: 10px;
  font-size: 14px;
  color: #909399;
}

.action-buttons {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.action-buttons .el-button {
  width: 100%;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.action-buttons .el-button--primary {
  background: linear-gradient(135deg, #C8102E 0%, #D4AF37 100%);
  border: none;
}

.action-buttons .el-button--primary:hover {
  background: linear-gradient(135deg, #D91E36 0%, #E6C866 100%);
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(212, 175, 55, 0.4);
}

.reviews-list {
  max-height: 400px;
  overflow-y: auto;
}

.review-item {
  padding: 15px 0;
  border-bottom: 1px solid #ebeef5;
}

.review-item:last-child {
  border-bottom: none;
}

.image-error-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  color: #909399;
  font-size: 14px;
}

.image-error-slot .el-icon {
  font-size: 48px;
  margin-bottom: 8px;
}

.review-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.review-user {
  font-weight: 600;
  color: #303133;
}

.review-date {
  margin-left: auto;
  font-size: 12px;
  color: #909399;
}

.review-content {
  color: #606266;
  line-height: 1.6;
  margin-top: 8px;
}
</style>

